gh-151912: Fix segfault in type() with NULL tp_new metaclasses#151916
gh-151912: Fix segfault in type() with NULL tp_new metaclasses#151916Santhosh-I wants to merge 9 commits into
type() with NULL tp_new metaclasses#151916Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
There was a problem hiding this comment.
Pull request overview
Fixes a crash in CPython’s type(name, bases, namespace) code path when metaclass resolution selects a metaclass whose tp_new slot is NULL (i.e., not instantiable), by raising a TypeError instead of calling through a NULL function pointer.
Changes:
- Add a
winner->tp_new == NULLguard before delegating to a non-type_newmetaclass constructor. - Raise
TypeError: cannot create '<metaclass>' instancesrather than segfaulting.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| PyErr_Format(PyExc_TypeError, | ||
| "cannot create '%.400s' instances", | ||
| winner->tp_name); |
| /* Check if tp_new is NULL (cannot instantiate this type) */ | ||
| if (winner->tp_new == NULL) { | ||
| PyErr_Format(PyExc_TypeError, | ||
| "cannot create '%.400s' instances", | ||
| winner->tp_name); | ||
| return -1; | ||
| } | ||
| /* Pass it to the winner */ | ||
| *type = winner->tp_new(winner, ctx->args, ctx->kwds); | ||
| if (*type == NULL) { |
type() with NULL tp_new metaclasses
sobolevn
left a comment
There was a problem hiding this comment.
Please, add a test case. This is an important code path.
|
Hi @sobolevn, Thanks! I can certainly add a regression test. Since the original reproducer relies on NumPy's DTypeMeta (tp_new == NULL), what would you recommend as the best way to exercise this case in the CPython test suite? Should this use one of the existing C test helpers, or should I add a small test type with tp_new == NULL? |
|
Yes, you can add the test into |
Summary
Fix a crash in
type(...)when the provided metaclass hastp_new == NULL.Currently,
type(name, bases, namespace)can reach a code path that calls:without verifying that
winner->tp_newis non-NULL. For metaclasses that are valid base classes at the C level but cannot be instantiated from Python (tp_new == NULL), this results in a segmentation fault.This change adds validation to reject such metaclasses and raise a Python exception instead.
Bug
For example, on NumPy main:
where
metaclass_instance == np.dtype, can eventually dereference a NULLtp_newpointer.The expected behavior is consistent with:
which raises:
Fix
winner) has a validtp_new.TypeErrorwhentp_new == NULLinstead of attempting to call it.Issue
Closes gh-151912. #151912